package com.qf.spring.aop.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.util.Arrays;

/**
 * @author zed
 * @date 2022/4/26 15:59
 * 增强类，五种增强方法都定义在这个类中
 */
@Aspect  // 声明当前类是一个增强类
@Component  // 当前类的实例注入Spring容器中 <bean id="" class="" />
public class UserAdvice {

    // 把切入点表达式抽出来，定义一个切入点 id=pointCut()
    @Pointcut("execution(* com.qf.spring.aop.service..*.*(..))")
    public void pointCut(){}

    // 前置增强 JoinPoint：连接点
    // Before 这个注解表示这个方法是前置增强的方法
    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        System.out.println("前置增强执行了。。。。");
        Object target = joinPoint.getTarget();
        System.out.println("目标对象是:" + target);
        System.out.println("方法名字："+joinPoint.getSignature().getName());
        Object[] args = joinPoint.getArgs();
        System.out.println("参数是："+Arrays.toString(args));
    }

    // 后置增强
    @AfterReturning(value = "pointCut()",returning = "result")
    public Object afterReturning(Object result){
        // result 目标方法的返回值
        System.out.println("后置增强执行了。。。。");
        return result;
    }

    // 前置最终增强
    @After("pointCut()")
    public void after(){
        System.out.println("最终增强执行了。。。。");
    }

    // 环绕增强 ProceedingJoinPoint是JoinPoint的子接口
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint jp){
        Object result= null;
        try {
            // 统计目标方法的执行时间,Spring提供了一个计时器
            StopWatch stopWatch = new StopWatch();
            // 开始及时
            stopWatch.start();
            System.out.println("环绕增强执行了。。前。。");
            // 决定目标方法是否继续执行 result:目标方法的返回值
            result = jp.proceed();
            System.out.println("环绕增强执行了。。后。。");
            // 结束计时
            stopWatch.stop();

            System.out.println("业务方法的执行时间为:"+stopWatch.getTotalTimeMillis()+"毫秒");
        }catch (Throwable e){
            e.printStackTrace();
        }
        return result;
    }

    // 异常抛出增强增强
    @AfterThrowing(value = "pointCut()",throwing = "e")
    public void throwing(Exception e){
        System.out.println("异常超出增强..");
        System.out.println("抛出的异常是:" + e.getMessage());
    }
}
